#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include "keycode.h"

static int monitor_num;		
static int camera_num;
static int run_val, hold_val;

static char * sub_string(unsigned char * des, unsigned char * src, unsigned int len)
{
	char *tmp = des;

	while(len > 0 && len--) {
		*des++ = *src++;
	}

	return tmp;
}

int ret_monitor(unsigned char * buf, unsigned char * keycode, unsigned int len)
{
	if (len == 3)
		return atoi(sub_string(buf, keycode, 1));
	else if (len == 4)
		return atoi(sub_string(buf, keycode, 2));
	else if (len == 5) 
		return atoi(sub_string(buf, keycode, 3));	
}

int ret_value(unsigned char * buf, unsigned char * keycode, unsigned int len)
{
	if (len == 8)
		return atoi(sub_string(buf, keycode+5, 1));
	else if (len == 9)
		return atoi(sub_string(buf, keycode+5, 2));
	else if (len == 10) 
		return atoi(sub_string(buf, keycode+5, 3));
	else if (len == 11) 
		return atoi(sub_string(buf, keycode+5, 4));
}

int ProcessKey(unsigned  char * keycode)
{
	int lock;	
	int salvo_val;
	int speed = 0;
	char buf[256];
	int len;
	int shot_set_value;	// 设置预置位
	int shot_value = 0;		// 调用预置位

	enPtzAction action;
	TReqPtzAct ptzact;
	TDeviceInfo	*pmonitor, *pcamera;	
	
	if ( keycode == NULL) {
		perror("key code was null!\n");
		return -1;
	}
	
	memset(buf, 0, sizeof buf);	
	keycode_trace(LEVEL_2, "\t[[ %s ]]\n", keycode);
	len = strlen(keycode);
	keycode_trace(LEVEL_2, "length is [%d]", len);

	switch(keycode[len - 2]) {		
		case 'M':	/* 选择监视器 */
			monitor_num = ret_monitor(buf, keycode, len);
			//printf("monitor num = %d\n", monitor_num);
			break;
		
		case '#':	/* 选择摄像机 */
			camera_num = ret_value(buf, keycode, len);
			//printf("camrema num = %d\n", camera_num);
			break;		
		
		case '^':	/* 预置设置 */
			shot_value = ret_value(buf, keycode, len);
			//printf("shot_set_value num = %d\n", shot_value);
			action = PTZ_SET_POINT;
			break;
		
		case '\\':	/* 预置调用 */
			shot_value = ret_value(buf, keycode, len);
			//printf("shot_call_value num = %d\n", shot_value);
			action = PTZ_GOTO_POINT;
			break;
		
		case 'K':	/* 锁定 */
			lock = 1;
			break;
		
		case 'J':	/* 解锁 */
			lock = 0;
			break;
		
		case 'S':	/* 按组号轮巡 */
			run_val = ret_value(buf, keycode, len);
			printf("run_val num = %d\n", run_val);
			break;
		
		case '$':	/* 成组切换 */
			salvo_val = ret_value(buf, keycode, len);
			//printf("salvo_val num = %d\n", salvo_val);
			break;
		
		case 'H':	/* 暂停正在运行的巡视 */
			hold_val = ret_value(buf, keycode, len);
			printf("hold_val num = %d\n", hold_val);
			break;

		case 'U':	/* 向上 */
			if (strlen(keycode) == 7)
				speed = 6;
			else
				speed = atoi(sub_string(buf,keycode+5,1));
			//printf("speed num = %d\n", speed);
			if (speed > 0)
				action = PTZ_UP_START;
			else if (speed == 0)
				action = PTZ_UP_STOP;
			break;	
		case 'D':	/* 向下 */
			if (strlen(keycode) == 7)
				speed = 6;
			else
				speed = atoi(sub_string(buf,keycode+5,1));
			//printf("speed num = %d\n", speed);
			if (speed > 0)
				action = PTZ_DOWN_START;
			else
				action = PTZ_DOWN_STOP;
			break;
		case 'L':	/* 向左 */
			if (strlen(keycode) == 7)
				speed = 6;
			else
				speed = atoi(sub_string(buf,keycode+5,1));
			//printf("speed num = %d\n", speed);
			if (speed > 0)
				action = PTZ_LEFT_START;
			else
				action = PTZ_LEFT_STOP;			
			break;
		case 'R':	/* 向右 */
			if (strlen(keycode) == 7)
				speed = 6;
			else				
				speed = atoi(sub_string(buf,keycode+5,1));
			//printf("speed num = %d\n", speed);
			if (speed > 0)
				action = PTZ_RIGHT_START;
			else
				action = PTZ_RIGHT_STOP;
			break;

		case 'O':	/* 光圈开 */
			action = PTZ_IRIS_OPEN_START;
			break;
		case 'C':	/* 光圈关 */
			action = PTZ_IRIS_CLOSE_START;
			break;

		case 'N':	/* 焦点近 */
			action = PTZ_FOCUS_NEAR_START;
			break;
		case 'F':	/* 焦点远 */
			action = PTZ_FOCUS_FAR_START;
			break;

		case 'W':	/* 焦距长 */
			action = PTZ_ZOOM_WIDE_START;
			break;
		case 'T':	/* 焦距短 */
			action = PTZ_ZOOM_TELE_START;
			break;

		default:
			break;
	}

	TDeviceInfo	*hold_pmonitor, *hold_pcamera;
	pmonitor = search(monitor_num, MONITOR);
	pcamera = search(camera_num, CAMERA);

	// 切换
	if ((monitor_num > 0 && camera_num > 0) && (pmonitor && pcamera)) {
		SwitchCamera(pmonitor, pcamera);
	}

	// 云台控制,预置设置,预置调用
	if (camera_num > 0 && pcamera) {
		ptzact.ActParam.Param1 = speed;
		if ((action == PTZ_SET_POINT || action == PTZ_GOTO_POINT) && shot_value > 0)
			ptzact.ActParam.Param1 = shot_value;

		PtzControl(pcamera->IP, pcamera->Port, pcamera->ChanNum, action, ptzact.ActParam);
	}

	// 轮巡
	if (run_val > 0) {
		grouplist *head, *newnode, *posnode;
		struct list_head *pos;

		NEW_LIST_NODE(grouplist, head);
		INIT_LIST_HEAD(&head->list);

		get_signle_group(head, newnode, run_val);
	

		list_for_each(pos, &(head->list)) {
			posnode = list_entry(pos, grouplist, list);
			print_result(posnode);
			
			if (pmonitor == NULL)
				return ;
			pcamera = search(posnode->group.CameraNo, CAMERA);
			if (pcamera) {
				// 切换
				SwitchCamera(pmonitor, pcamera);
				// 预置调用
				if (posnode->group.PresetNo > 0) {
					action = PTZ_GOTO_POINT;
					ptzact.ActParam.Param1 = posnode->group.PresetNo;
					PtzControl(pcamera->IP, pcamera->Port, pcamera->ChanNum, action, ptzact.ActParam);
				}
				sleep(posnode->group.StopTime);
			}
		}
		
		// 释放存取单个group数据的双链表
		FREE_LIST(grouplist, head, list);
	}

	// 停止轮巡
	if (hold_val > 0) {

	}

	return 0;
}

void * run_operate(void * arg)
{
	grouplist *head, *newnode, *posnode;
	struct list_head *pos;
	TDeviceInfo	*pmonitor, *pcamera;	
	enPtzAction action;
	TReqPtzAct ptzact;

	NEW_LIST_NODE(grouplist, head);
	INIT_LIST_HEAD(&head->list);

	get_signle_group(head, newnode, run_val);


	list_for_each(pos, &(head->list)) {
		posnode = list_entry(pos, grouplist, list);
		print_result(posnode);
		
		pcamera = search(posnode->group.CameraNo, CAMERA);
		if (pcamera) {
			// 切换
			SwitchCamera(pmonitor, pcamera);
			// 预置调用
			if (posnode->group.PresetNo > 0) {
				action = PTZ_GOTO_POINT;
				ptzact.ActParam.Param1 = posnode->group.PresetNo;
				PtzControl(pcamera->IP, pcamera->Port, pcamera->ChanNum, action, ptzact.ActParam);
			}
			sleep(posnode->group.StopTime);
		}
	}
	
	// 释放存取单个group数据的双链表
	FREE_LIST(grouplist, head, list);
}

static int hold_operate(unsigned int val)
{}

pthread_t keycode[5];
typedef int (*function) (unsigned  char * keycode);

int run_callback(int mon, int carm, function code)
{
	code = ProcessKey;
}


void run()
{
	int err;
	int i;

	for (i = 0; i < sizeof(keycode) / sizeof(keycode[0]); i++) {
		err = pthread_create(&keycode[i], NULL, run_operate, NULL);
		if (err != 0)	
			printf("can't create thread i : %d\n", i);
	}

	void *ptr;
	for (i = 0; i < sizeof(keycode) / sizeof(keycode[0]); i++) {
		pthread_join(keycode[i], &ptr);
	}
}

